import subprocess

from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget, QGridLayout, QLabel, QSpinBox, QMessageBox, QButtonGroup, QRadioButton, QGroupBox, \
    QVBoxLayout


class EnableGrub(QWidget):

    def disable_grub(self):

        dlg = QMessageBox()
        dlg.setWindowTitle('Внимание!')
        dlg.setText('Вы действительно хотите отключить меню GRUB?')
        dlg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
        if dlg.exec() == QMessageBox.Ok:
            with open(self.filename) as inp:
                lines = inp.readlines()
                hidden_timeout_found = False
            for i in range(len(lines)):
                lines[i] = lines[i].strip()
                if 'GRUB_TIMEOUT' in lines[i]:
                    lines[i] = 'GRUB_TIMEOUT=0'
                elif 'GRUB_HIDDEN_TIMEOUT' in lines[i]:
                    lines[i] = 'GRUB_HIDDEN_TIMEOUT=$GRUB_TIMEOUT'
                    hidden_timeout_found = True

            if not hidden_timeout_found:
                lines.append('GRUB_HIDDEN_TIMEOUT=$GRUB_TIMEOUT')

            with open(self.filename, 'w') as out:
                print(*lines, sep='\n', file=out)
            update_code = subprocess.run('update-grub2', shell=True, capture_output=True).returncode
            msg = 'Меню GRUB отключено.' if update_code == 0 else 'Ошибка обновления GRUB.'
            dlg2 = QMessageBox()
            dlg2.setWindowTitle('Внимание!')
            dlg2.setText(msg)
            dlg2.setFixedWidth(400)
            dlg2.exec()
            self.current_grub_config.setText(''.join(open(self.filename).readlines()))

    def set_grub_timeout(self):

        index_to_remove = -1
        with open(self.filename) as inp:
            lines = inp.readlines()
        for i in range(len(lines)):
            lines[i] = lines[i].strip()
            if 'GRUB_TIMEOUT' in lines[i]:
                lines[i] = f'GRUB_TIMEOUT={self.grub_timeout.value()}'
            elif 'GRUB_HIDDEN_TIMEOUT' in lines[i]:
                index_to_remove = i

        if index_to_remove != -1:
            lines = lines[:index_to_remove] + lines[index_to_remove + 1:]

        with open(self.filename, 'w') as out:
            print(*lines, sep='\n', file=out)

        update_code = subprocess.run('update-grub2', shell=True, capture_output=True).returncode
        msg = f'GRUB включён, интервал при загрузке {self.grub_timeout.value()} c.' if update_code == 0 else \
            'Ошибка обновления GRUB.'
        dlg = QMessageBox()
        dlg.setWindowTitle('Внимание!')
        dlg.setText(msg)
        dlg.exec()

    def grub_action(self):
        if self.enable_grup_radiobox.isChecked():
            self.set_grub_timeout()
        else:
            self.disable_grub()

    def is_grub_enabled(self):
        res = True
        with open(self.filename) as inp:
            lines = inp.readlines()
        for i in range(len(lines)):
            lines[i] = lines[i].strip()
            if 'GRUB_TIMEOUT=0' in lines[i] or \
                    ('GRUB_HIDDEN_TIMEOUT=' in lines[i] and not lines[i].strip().startswith('#')):
                res = False
        return res

    def get_grub_timeout(self):
        with open(self.filename) as inp:
            lines = inp.readlines()
        try:
            for i in range(len(lines)):
                lines[i] = lines[i].strip()
                if 'GRUB_TIMEOUT' in lines[i]:
                    return int(lines[i].split('=')[-1].strip())
        except Exception:
            return 0
        return 0

    def update_changes(self):
        if self.is_grub_enabled():
            if self.disable_grup_radiobox.isChecked():
                self.changes_label.setText('GRUB будет отключён (сейчас включён).')
            elif self.get_grub_timeout() != self.grub_timeout.value():
                self.changes_label.setText(f'Будет установлена задержка {self.grub_timeout.value()} секунд '
                                           f'(сейчас {self.get_grub_timeout()})')
            else:
                self.changes_label.setText('')
        elif not self.is_grub_enabled():
            if self.enable_grup_radiobox.isChecked():
                text = 'GRUB будет включён (сейчас отключён). '
            else:
                text = ''
            if self.get_grub_timeout() != self.grub_timeout.value():
                text += f'Будет установлена задержка {self.grub_timeout.value()} секунд ' \
                        f'(сейчас {self.get_grub_timeout()})'
            self.changes_label.setText(text)

    def __init__(self):
        super().__init__()

        self.filename = '/etc/default/grub'
        layout = QGridLayout()
        self.setLayout(layout)

        grub_settings_label = QLabel('Настройка GRUB')
        grub_settings_label.setAlignment(Qt.AlignCenter)
        layout.addWidget(grub_settings_label, 0, 0, 1, 2)
        state_label = QLabel('Состояние: ')
        state_label.setAlignment(Qt.AlignTop|Qt.AlignRight)
        layout.addWidget(state_label, 1, 0)

        switch_grub_radioboxes = QButtonGroup(self)
        self.enable_grup_radiobox = QRadioButton('Включено')
        self.disable_grup_radiobox = QRadioButton('Выключено')
        switch_grub_radioboxes.addButton(self.enable_grup_radiobox)
        switch_grub_radioboxes.addButton(self.disable_grup_radiobox)
        layout.addWidget(self.enable_grup_radiobox, 1, 1)
        layout.addWidget(self.disable_grup_radiobox, 2, 1)
        if self.is_grub_enabled():
            self.enable_grup_radiobox.setChecked(True)
        else:
            self.disable_grup_radiobox.setChecked(True)
        self.enable_grup_radiobox.toggled.connect(self.update_changes)
        self.grub_file_contents_groupbox = QGroupBox(self.filename)
        self.grub_file_contents_groupbox_layout = QVBoxLayout()
        self.grub_file_contents_groupbox.setLayout(self.grub_file_contents_groupbox_layout)
        self.current_grub_config = QLabel()
        self.current_grub_config.setText(''.join(open(self.filename).readlines()))
        self.grub_file_contents_groupbox_layout.addWidget(self.current_grub_config)
        layout.addWidget(self.grub_file_contents_groupbox, 3, 0, 1, 2)

        select_interval_label = QLabel('Интервал при загрузке: ')
        select_interval_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        layout.addWidget(select_interval_label, 4, 0)
        self.grub_timeout = QSpinBox()
        self.grub_timeout.setRange(1, 60)
        self.grub_timeout.setValue(self.get_grub_timeout())
        self.grub_timeout.valueChanged.connect(self.update_changes)
        self.grub_timeout.setToolTip('Значение от 1 до 60')
        layout.addWidget(self.grub_timeout, 4, 1)

        changes_header_label = QLabel('Вносимые изменения: ')
        changes_header_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        layout.addWidget(changes_header_label, 5, 0)
        self.changes_label = QLabel('')
        self.changes_label.setWordWrap(True)
        layout.addWidget(self.changes_label, 5, 1)
